package datasource;

import org.apache.pdfbox.contentstream.PDFStreamEngine;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.contentstream.operator.OperatorName;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDStream;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class RemoveTextElementFromPDF {
    public static void main(String[] args) {
        try (PDDocument document = PDDocument.load(new File("D:\\yummeng\\test.pdf"))) {
            String textToRemove = "Evaluation Warning : The document was created with Spire.PDF for Java.";
            for (PDPage page : document.getPages()) {
                removeFirstOccurrenceOfTextFromPage(document, page, textToRemove);
            }
            document.save("D:\\yummeng\\output_modified123.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void removeFirstOccurrenceOfTextFromPage(PDDocument document, PDPage page, String textToRemove) throws IOException {
        CustomPDFStreamEngine engine = new CustomPDFStreamEngine();
        engine.setTextToRemove(textToRemove);

        // 处理页面内容流
        engine.processPage(page);

        // 重新设置页面的内容流
        PDStream newContentStream = new PDStream(document);
        try (OutputStream outputStream = newContentStream.createOutputStream();
             PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.OVERWRITE, true, true)) {
            engine.writeTo(contentStream);
        }
        page.setContents(newContentStream);
    }

    private static class CustomPDFStreamEngine extends PDFStreamEngine {
        private boolean textRemoved = false;
        private String textToRemove;
        private List<Operator> operators = new ArrayList<>();
        private List<List<COSBase>> operandsList = new ArrayList<>();

        public void setTextToRemove(String textToRemove) {
            this.textToRemove = textToRemove;
        }

        @Override
        public void showTextString(byte[] string) throws IOException {
            String text = new String(string);
            if (!textRemoved && text.contains(textToRemove)) {
                // 找到第一个匹配的文本并移除
                String modifiedText = text.replaceFirst(textToRemove, "");
                if (!modifiedText.isEmpty()) {
                    super.showTextString(modifiedText.getBytes());
                }
                textRemoved = true;
            } else {
                super.showTextString(string);
            }
        }

        @Override
        public void processOperator(Operator operator, List<COSBase> operands) throws IOException {
            String operatorName = operator.getName();
            if (operatorName.equals(OperatorName.SHOW_TEXT) ||
                    operatorName.equals(OperatorName.SHOW_TEXT_LINE) ||
                    operatorName.equals(OperatorName.SHOW_TEXT_LINE_AND_SPACE)) {
                // 处理文本显示操作符
                COSBase base = operands.get(0);
                if (base instanceof COSString) {
                    COSString cosString = (COSString) base;
                    String text = cosString.getString();
                    if (!textRemoved && text.contains(textToRemove)) {
                        String modifiedText = text.replaceFirst(textToRemove, "");
                        if (!modifiedText.isEmpty()) {
                            operands.set(0, new COSString(modifiedText));
                        } else {
                            // 如果文本为空，跳过该操作符
                            return;
                        }
                        textRemoved = true;
                    }
                }
            }
            // 记录操作符和操作数
            operators.add(operator);
            operandsList.add(new ArrayList<>(operands));
        }

        public void writeTo(PDPageContentStream contentStream) throws IOException {
            for (int i = 0; i < operators.size(); i++) {
                Operator operator = operators.get(i);
                List<COSBase> operands = operandsList.get(i);

                // 处理文本显示操作符
                if (operator.getName().equals(OperatorName.SHOW_TEXT) ||
                        operator.getName().equals(OperatorName.SHOW_TEXT_LINE) ||
                        operator.getName().equals(OperatorName.SHOW_TEXT_LINE_AND_SPACE)) {
                    COSBase base = operands.get(0);
                    if (base instanceof COSString) {
                        COSString cosString = (COSString) base;
                        String text = cosString.getString();
                        // 写入文本内容
                        contentStream.showText(text);
                    }
                } else {
                    // 处理其他操作符（如果需要）
                    // 例如：contentStream.addOperator(operator.getName());
                }
            }
        }
    }
}
